#include<iostream>
#include<stdio.h>
#include<string.h>
#include<string>
#include<assert.h>
#include<stdlib.h>
#include<iostream>
#include<fcntl.h>
#include<unistd.h>
#include"sockadd.h"
#include"threadpool.h"
#include"http_conn.h"
#include<sys/wait.h>
#include<netinet/in.h>
#include<arpa/inet.h> 
#include<sys/socket.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<errno.h>
#include<sys/epoll.h>
#include<sys/sendfile.h>
void addsig(int sig,void(handler)(int)){
    struct sigaction sa;
    memset(&sa,'\0',sizeof(sa));
    sa.sa_handler=handler;
    sigfillset(&sa.sa_mask);
    assert( sigaction( sig, &sa, NULL ) != -1 );
}
using namespace std;
int main(){

    addsig(SIGPIPE,SIG_IGN);//对中断SIGPIPE信号忽略
    /*如果一个 socket 在接收到了 RST packet 之后，程序仍然向这个 socket 写入数据，那么就会产生SIGPIPE信号。 
    这种现象是很常见的，譬如说，当 client 连接到 server 之后，这时候 server 准备向 client 发送多条消息，
    但在发送消息之前， client 进程意外奔溃了，
    那么接下来 server 在发送多条消息的过程中，就会出现SIGPIPE信号*/
    
    //创建线程池
    threadpool<http_conn> * pool=NULL;
    
    try{
    pool=new threadpool<http_conn>;
    }catch(...){
        printf("内存分配错误");
        exit(-1);
    }
    
    http_conn * users=new http_conn[65000];//http保存客户端信息且执行真正的操作
    

    int listenfd=sockadd();//主sock
    
    epoll_event events[10000];

    int epollfd=epoll_create(1);//创建epoll

    addfd( epollfd, listenfd, false );
    http_conn::m_epollfd = epollfd;

    while(true)
    {
        int num=epoll_wait(epollfd,events,10000,-1);
        if((num<0)&&(errno!=EINTR)&&(errno!=9)){
          printf("epollfd failure\n");
          cout<<errno;
          break;
        }
        
    for(int i=0;i<num;i++){
        int sockfd=events[i].data.fd;
        if(sockfd==listenfd){
            struct sockaddr_in client_address;
            socklen_t addrlen=sizeof(client_address);
            int connfd=accept(listenfd,(struct sockaddr*)&client_address,&addrlen);
            if(http_conn::m_user_count>=65000){//请求队列爆满,可以回复一个信息
            close(connfd);
            printf("请求队列爆满,可以回复一个信息\n");
            continue;
            }
            users[connfd].init(connfd,client_address);
            //cout<<"接受链接"<<endl;
        }
        else if(events[i].events&(EPOLLHUP|EPOLLERR)){//EPOLLRDHUP|EPOLLHUP|EPOLLERR
            //异常断开链接
            users[sockfd].close_conn();
            if(events[i].events&EPOLLRDHUP){cout<<"EPOLLRDHUP";}
            if(events[i].events&EPOLLHUP){cout<<"EPOLLHUP";}
            if(events[i].events&EPOLLERR){cout<<"EPOLLERR";}
            cout<<"异常断开链接"<<endl;
        }
        else if(events[i].events&EPOLLIN){//读取
        
            if(users[sockfd].read()){
                pool->append(users+sockfd);
                //cout<<"一次性读取链接"<<endl;
            }
            else{//pool->append(users+sockfd);
                users[sockfd].close_conn();
                cout<<"读取链接不完整"<<endl;
            }
        }
        else if(events[i].events&EPOLLOUT){//写入
            if(!users[sockfd].write()){
                users[sockfd].close_conn();
                //cout<<"写完数据断开链接"<<endl;
            }
        }
    }

}
    close(epollfd);close(listenfd);delete[] users;delete pool;
	return 0;
}